use std::collections::HashMap;
use crate::utils::Error;
use crate::utils::HttpError::UnrecognizedRequest;

#[derive(Debug)]
pub struct HttpRequest {
    pub method: Method,
    pub version: Version,
    pub path: String,
    pub headers: HashMap<String, String>,
    pub body: String,
}

impl HttpRequest {
    ///从接受的字符转化为Request结构体
    pub fn from_string(req: String) -> Result<Self, Error> {
        let mut request = HttpRequest {
            method: Method::GET,
            version: Version::HttpV11,
            path: "/".to_string(),
            headers: Default::default(),
            body: "".to_string(),
        };
        //逐行解析
        for line in req.lines() {
            if line.contains("HTTP") {
                //信息行把方法、路径和版本分离出来
                let e = Err(Error::HttpError(UnrecognizedRequest));
                let mut words = line.split_whitespace();
                request.method = match words.next() {
                    None => { return e; }
                    Some(s) => { s.into() }
                };
                request.path = match words.next() {
                    None => { return e; }
                    Some(s) => { s.into() }
                };
                request.version = match words.next() {
                    None => { return e; }
                    Some(s) => { s.into() }
                };
            } else if line.contains(":") && !line.contains("}") {
                //请求头行，拆分插入HashMap
                let mut header = line.split(":");
                let (mut key, mut value) = ("".to_string(), "".to_string());
                if let Some(k) = header.next() {
                    key = k.to_string();
                };
                if let Some(v) = header.next() {
                    value = v.to_string();
                }
                request.headers.insert(key, value);
            } else if line.len() != 0 {
                //请求题
                request.body += line.trim_end_matches(|c| c == '\0' || c == '\r')
            }
        }
        return Ok(request);
    }
}

//请求方法枚举类
#[derive(Debug)]
pub enum Method {
    GET,
    POST,
    Others,
}

#[derive(Debug)]
pub enum Version {
    HttpV11,
    HttpV2,
    Others,
}

// 为Method枚举实现从字符串切片到枚举类的trait
impl From<&str> for Method {
    fn from(s: &str) -> Self {
        match s {
            "GET" => Method::GET,
            "POST" => Method::POST,
            _ => Method::Others
        }
    }
}

impl From<&str> for Version {
    fn from(value: &str) -> Self {
        match value {
            "HTTP/1.1" => Version::HttpV11,
            "HTTP/2" => Version::HttpV2,
            _ => Version::Others
        }
    }
}